<!-- 搜索之后的返回的选项组件 -->
<template>
  <scroll class="suggest"
          :data="result"
          :pullup="pullup"
          @scrollToEnd="searchMore"
          ref="suggest"
          :beforeScroll="beforeScroll"
          @beforeScroll="listScroll">
    <ul class="suggest-list">
      <!-- 点击跳转search的二级路由 -->
      <li @click="selectItem(item)"
          class="suggest-item"
          v-for="(item, index) in result"
          :key="index">
        <div class="icon">
          <!-- 动态添加class，即样式 -->
          <i :class="getIconCls(item)"></i>
        </div>
        <div class="name">
          <p class="text" v-html="getDisplayName(item)"></p>
        </div>
      </li>
      <loading v-show="hasMore" title=""></loading>
    </ul>
    <!-- 搜索不到后的效果 -->
    <!-- 在没有加载完,且在没有后端数据返回的时候 -->
    <div v-show="!hasMore && !result.length" class="no-result-wrapper">
      <no-result title="抱歉，暂无搜索结果"></no-result>
    </div>
  </scroll>
</template>

<script>
// 调用点击热门歌曲返回到input上后，向后端发送的请求的方法
import {search} from 'api/search'
// 常量
import {ERR_OK} from 'api/config'
// 引用筛选方法换成screateSong方法
import {createSong, processSongsUrl} from 'common/js/song'
// 引入scroll组件
import Scroll from 'base/scroll/scroll'
// loading
import Loading from 'base/loading/loading'
// Singer改造数据结构的方法
import Singer from 'common/js/singer'
// 引入vuex
import {mapMutations, mapActions} from 'vuex'
// 引入代表没有结果的NoResult组件
import NoResult from 'base/no-result/no-result'

const TYPE_SINGER = 'singer'

const perpage = 20

export default {
  props: {
    // 从父组件接收query数据
    query: {
      type: String,
      default: ''
    },
    showSinger: {
      type: Boolean,
      default: true
    }
  },
  data () {
    return {
      // 默认设置page了
      page: 1,
      // 接收后端返回的数据
      result: [],
      // 上拉刷新是否开启
      // 这个页面就是在输入东西的时候打开，然后就把pullup传入到scroll开启
      pullup: true,
      // 判断有没有加载完的标识位
      hasMore: true,
      // 让scroll子组件调用beforeScrollStart事件
      beforeScroll: true
    }
  },
  methods: {
    // 服务端的逻辑封装的方法
    search () {
      this.page = 1
      // 在搜索的时候赋值true,因为每新一轮获取都是默认不要刷新的
      this.hasMore = true
      // 回到顶部
      this.$refs.suggest.scrollTo(0, 0)
      // query代表检索的字，page代表检索第几页，zhida代表要不要歌手的数据
      search(this.query, this.page, this.showSinger, perpage).then((res) => {
        if (res.code === ERR_OK) {
          this._genResult(res.data).then((result) => {
            this.result = result
          })
          // 拿到的后端返回的数据,判断一下，没有可以刷新的数据了还是有
          this._checkMore(res.data)
        }
      })
    },
    // 点击跳转详情页
    selectItem (item) {
      // 如果时它是一个歌手
      if (item.type === TYPE_SINGER) {
        // 用singer这个类构造一个数据结构
        const singer = new Singer({
          id: item.singermid,
          name: item.singername
        })
        // 路由跳转到数据结构对应的id
        this.$router.push({
          path: `/search/${singer.id}`
        })
        // 修改vuex中state的值,然后之前的设置会继续执行成想要的效果
        this.setSinger(singer)
        // 否则不是歌手的时候
      } else {
        // 也是修改vuex中state的值
        this.insertSong(item)
      }
      // 派发到一个事件就行了，为了改变state
      this.$emit('select')
    },
    // 接收到了该刷数据的时机
    searchMore () {
      // 如果hasMore是false，就不执行了
      if (!this.hasMore) {
        return
      }
      this.page++
      // 调用发送到后端的数据
      search(this.query, this.page, this.showSinger, perpage).then((res) => {
        if (res.code === ERR_OK) {
          this.result = this.result.concat(this._genResult(res.data))
          // 拿到的后端返回的数据,判断一下，没有可以刷新的数据了还是有
          this._checkMore(res.data)
        }
      })
    },
    // 动态添加class
    getIconCls (item) {
      if (item.type === TYPE_SINGER) {
        return 'icon-mine'
      } else {
        return 'icon-music'
      }
    },
    getDisplayName (item) {
      if (item.type === TYPE_SINGER) {
        return item.singername
      } else {
        return `${item.name}-${item.singer}`
      }
    },
    refresh () {
      this.$refs.suggest.refresh()
    },
    // scroll组件启动beforeScrollStart事件后的回调函数
    listScroll () {
      this.$emit('listScroll')
    },
    // 判断一下，没有可以刷新的数据了还是有
    _checkMore (data) {
      const song = data.song
      // 如果成立时，就是false，就是没有更多了
      if (!song.list.length || (song.curnum + song.curpage * perpage) >= song.totalnum) {
        this.hasMore = false
      }
    },
    // 处理返回的数据的结构的函数
    _genResult (data) {
      let ret = []
      if (data.zhida && data.zhida.singerid && this.page === 1) {
        // ...data.zhida代表data里面zhida所有的数据
        // es6的东西和什么...mapMutations一样的用法
        ret.push({...data.zhida, ...{type: TYPE_SINGER}})
      }
      // if (data.song) {
      //   ret = ret.concat(this._normalizeSongs(data.song.list))
      // }
      // return ret
      return processSongsUrl(this._normalizeSongs(data.song.list)).then((songs) => {
        ret = ret.concat(songs)
        return ret
      })
    },
    // 这个方法是为了封装,处理数据,本质上还是使用filterSinger方法
    _normalizeSongs (list) {
      let ret = []
      list.forEach((musicData) => {
        if (musicData.songid && musicData.albumid) {
          ret.push(createSong(musicData))
        }
      })
      return ret
    },
    ...mapMutations({
      setSinger: 'SET_SINGER'
    }),
    ...mapActions([
      'insertSong'
    ])
  },
  watch: {
    // 监听query变化
    query () {
      // 一变化就调用方法
      this.search()
    }
  },
  components: {
    Scroll,
    Loading,
    NoResult
  }
}
</script>

<style scoped lang="stylus" rel="stylesheet/stylus">
  @import "~common/stylus/variable"
  @import "~common/stylus/mixin"

  .suggest
    height: 100%
    overflow: hidden
    .suggest-list
      padding: 0 30px
      .suggest-item
        display: flex
        align-items: center
        padding-bottom: 20px
      .icon
        flex: 0 0 30px
        width: 30px
        [class^="icon-"]
          font-size: 14px
          color: $color-text-d
      .name
        flex: 1
        font-size: $font-size-medium
        color: $color-text-d
        overflow: hidden
        .text
          no-wrap()
    .no-result-wrapper
      position: absolute
      width: 100%
      top: 50%
      transform: translateY(-50%)
</style>
